<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es5 原型继承关系图解</title>
  <!-- 
  在 JavaScript ES5 中，原型继承是一种重要的机制，它允许对象通过原型链共享属性和方法。
  1. 原型继承的基本概念
  - 原型：每个 JavaScript 对象都有一个内部属性  `[[Prototype]]` ，指向另一个对象，这个对象称为原型。
  - 原型链：通过原型链，子类可以访问父类的属性和方法。

  2. 原型继承的关系图解
  假设有一个父类  `Parent`  和一个子类  `Child` ，它们的原型继承关系可以通过以下步骤来描述：

   2.1 定义父类和子类
  function Parent() {
      this.parentProperty = "I am a parent property";
  }

  Parent.prototype.parentMethod = function() {
      console.log("This is a method from Parent");
  };

  function Child() {
      this.childProperty = "I am a child property";
  }

  // 继承 Parent
  Child.prototype = Object.create(Parent.prototype);
  Child.prototype.constructor = Child;

  Child.prototype.childMethod = function() {
      console.log("This is a method from Child");
  };
   2.2 关系图解
  可以用以下图示来表示它们的继承关系：
  +-------------------+
          |      Object       |  ← 所有对象的基类
          +-------------------+
                    ↑
                    |
          +-------------------+
          |      Parent       |  ← 父类
          +-------------------+
          | parentProperty     |
          +-------------------+
          | parentMethod()     |
          +-------------------+
                    ↑
                    |
          +-------------------+
          |      Child        |  ← 子类
          +-------------------+
          | childProperty      |
          +-------------------+
          | childMethod()      |
          +-------------------+
  3. 继承关系的解释
  - 父类 ( `Parent` )：包含实例属性  `parentProperty`  和原型方法  `parentMethod()` 。所有继承  `Parent`  的对象都可以访问这些属性和方法。
  - 子类 ( `Child` )：通过  `Child.prototype = Object.create(Parent.prototype)`  实现了对  `Parent`  的继承。子类可以访问父类的属性和方法，同时也可以定义自己的属性和方法。
  - 原型链：当访问  `childInstance.parentMethod()`  时，JavaScript 引擎首先查找  `Child`  的实例属性，如果没有找到，就会沿着原型链向上查找，最终找到  `Parent`  的  `parentMethod()` 。

  4. 总结
  原型继承是 JavaScript 中实现继承和共享属性的重要机制。通过理解原型链的结构和继承关系，开发者可以有效地构建对象模型，实现代码的重用和扩展。理解原型继承的关系图解对于掌握 JavaScript 的面向对象编程非常重要。
  -->
</head>

<body>

  <script>

    // const obj = {} // new Object()
    // obj.__proto__ // Object.prototype

    var obj = {}; // 相当于 var obj = new Object(); --> function Object(){}
    function Foo() { } // 相当于 var Foo = new Function(); --> function Function(){}
    function Person() { }

    // function Function/Object(){}
    const foo = new Foo()

    console.log(foo.__proto__ === Foo.prototype); // true
    console.log(Foo.prototype === Foo.prototype); // true
    console.log(Foo.prototype.__proto__ === Object.prototype); // true
    console.log(Foo.__proto__ === Function.prototype); // true

    console.log(obj.__proto__ === Object.prototype); // true
    console.log(/* function Object() {} */Object.__proto__ === Function.prototype); // true
    console.log(/* function Object() {} */Object.prototype === Object.prototype); // true
    console.log(/* Object.prototype */Object.prototype.__proto__ === null);

    console.log(/* function Function() {} */Function.__proto__ === Function.prototype); // true
    console.log(/* function Function() {} */Function.prototype === Function.prototype); // true
    console.log(/* function Function() {} */Function.prototype.__proto__ === Object.prototype); // true


  </script>

</body>

</html>